package com.douya.mvc.config;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.config.SentinelWebMvcConfig;
import com.douya.common.format.PagerDTOFormatter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 说明：MVC配置，包含类转化器和Long转化
 *
 * @Author 胡晨烨
 * @Date 2020/02/01
 */
@Configuration
public class WebMvcAutoConfig implements WebMvcConfigurer {

    @Resource
    ObjectMapper mObjectMapper;

    /**
     * 添加类转化器
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new PagerDTOFormatter());
    }

    /**
     * 添加Long转String的转化器，防止数值过大时在javascript中精度丢失
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        List<HttpMessageConverter<?>> oldConverter = converters.stream()
                .filter(converter -> converter instanceof MappingJackson2HttpMessageConverter)
                .collect(Collectors.toList());

        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        simpleModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        mObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mObjectMapper.registerModule(simpleModule);
        oldConverter.forEach(converter -> {
            ((MappingJackson2HttpMessageConverter) converter).getObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
            ((MappingJackson2HttpMessageConverter) converter).getObjectMapper().registerModule(simpleModule);
        });
    }

    /**
     * 添加Sentinel拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 集成Sentinel
        SentinelWebMvcConfig config = new SentinelWebMvcConfig();
        // 启用HTTP方法前缀。
        config.setHttpMethodSpecify(true);
        // 添加到拦截器列表中。
        registry.addInterceptor(new SentinelWebInterceptor(config)).addPathPatterns("/**");
    }
}
